home *** CD-ROM | disk | FTP | other *** search
/ Experimental BBS Explossion 3 / Experimental BBS Explossion III.iso / games / nhak_src.zip / LEV_COMP.Y < prev    next >
GNU Bison Grammar  |  1993-03-16  |  25KB  |  1,101 lines

  1. %{ 
  2. /*    SCCS Id: @(#)lev_comp.c    3.0    90/01/03
  3. /*    Copyright (c) 1989 by Jean-Christophe Collet */
  4. /* NetHack may be freely redistributed.  See license for details. */
  5.  
  6. /*
  7.  * This file contains the Level Compiler code
  8.  * It may handle special mazes & special room-levels
  9.  */
  10.  
  11. /* block some unused #defines to avoid overloading some cpp's */
  12. #define MONDATA_H    /* comment line for pre-compiled headers */
  13. #define MONFLAG_H    /* comment line for pre-compiled headers */
  14.  
  15. #include "hack.h"
  16. #include "sp_lev.h"
  17. #ifndef O_WRONLY
  18. # include <fcntl.h>
  19. #endif
  20. #ifndef O_CREAT    /* some older BSD systems do not define O_CREAT in <fcntl.h> */
  21. # include <sys/file.h>
  22. #endif
  23.  
  24. void FDECL(yyerror, (char *));
  25. void FDECL(yywarning, (char *));
  26. int NDECL(yylex);
  27. int NDECL(yyparse);
  28.  
  29. int FDECL(get_room_type, (char *));
  30. int FDECL(get_trap_type, (char *));
  31. int FDECL(get_monster_id, (char *, CHAR_P));
  32. int FDECL(get_object_id, (char *, CHAR_P));
  33. boolean FDECL(check_monster_char, (CHAR_P));
  34. boolean FDECL(check_object_char, (CHAR_P));
  35. void FDECL(scan_map, (char *));
  36. void NDECL(store_part);
  37. void FDECL(write_maze, (int, specialmaze *));
  38.  
  39. #ifdef AMIGA
  40. char *fgets();
  41. # undef     fopen
  42. # undef     printf
  43. # undef     Printf
  44. # define    Printf  printf
  45. #ifndef    LATTICE
  46. # define    memset(addr,val,len)    setmem(addr,len,val)
  47. #endif
  48. #endif
  49.  
  50. #ifdef MSDOS
  51. # undef exit
  52. extern void FDECL(exit, (int));
  53. #endif
  54.  
  55. #ifdef MACOS
  56. # undef printf
  57. # undef Printf
  58. # define Printf printf
  59. #endif
  60.  
  61. #undef NULL
  62.  
  63. #define MAX_REGISTERS    10
  64. #define ERR        (-1)
  65.  
  66. struct reg {
  67.     int x1, y1;
  68.     int x2, y2;
  69. }        current_region;
  70.  
  71. struct coord {
  72.     int x;
  73.     int y;
  74. }        current_coord;
  75.  
  76. struct {
  77.     char *name;
  78.     short type;
  79. } trap_types[TRAPNUM-1] = {
  80.     "monster",    MONST_TRAP,
  81.     "statue",    STATUE_TRAP,
  82.     "bear",        BEAR_TRAP,
  83.     "arrow",    ARROW_TRAP,
  84.     "dart",        DART_TRAP,
  85.     "trapdoor",    TRAPDOOR,
  86.     "teleport",    TELEP_TRAP,
  87.     "pit",        PIT,
  88.     "sleep gas",    SLP_GAS_TRAP,
  89.     "magic",    MGTRP,
  90.     "board",    SQBRD,
  91.     "web",        WEB,
  92.     "spiked pit",    SPIKED_PIT,
  93.     "level teleport",LEVEL_TELEP,
  94. #ifdef SPELLS
  95.     "anti magic",    ANTI_MAGIC,
  96. #endif
  97.     "rust",        RUST_TRAP
  98. #ifdef POLYSELF
  99.     , "polymorph",    POLY_TRAP
  100. #endif
  101. #ifdef ARMY
  102.     , "land mine",    LANDMINE
  103. #endif
  104.   };
  105.  
  106. struct {
  107.     char *name;
  108.     int type;
  109. } room_types[SHOPBASE-1] = {
  110.     /* for historical reasons, room types are not contiguous numbers */
  111.     /* (type 1 is skipped) */
  112.     "ordinary",    OROOM,
  113. #ifdef THRONES
  114.     "throne",    COURT,
  115. #endif
  116.     "swamp",    SWAMP,
  117.     "vault",    VAULT,
  118.     "beehive",    BEEHIVE,
  119.     "morgue",    MORGUE,
  120. #ifdef ARMY
  121.     "barracks",    BARRACKS,
  122. #endif
  123.     "zoo",        ZOO,
  124.     "temple",    TEMPLE,
  125.     "shop",        SHOPBASE,
  126. };
  127.  
  128. short db_dirs[4] = {
  129.     DB_NORTH,
  130.     DB_EAST,
  131.     DB_SOUTH,
  132.     DB_WEST
  133. };
  134.  
  135. #ifdef ALTARS
  136. static altar *tmpaltar[256];
  137. #endif /* ALTARS /**/
  138. static lad *tmplad[256];
  139. static digpos *tmpdig[256];
  140. static char *tmpmap[ROWNO];
  141. static region *tmpreg[16];
  142. static door *tmpdoor[256];
  143. static trap *tmptrap[256];
  144. static monster *tmpmonst[256];
  145. static object *tmpobj[256];
  146. static drawbridge *tmpdb[256];
  147. static walk *tmpwalk[256];
  148. static mazepart *tmppart[10];
  149. static room *tmproom[MAXNROFROOMS];
  150. static specialmaze maze;
  151.  
  152. static char olist[MAX_REGISTERS], mlist[MAX_REGISTERS];
  153. static struct coord plist[MAX_REGISTERS];
  154. static int n_olist = 0, n_mlist = 0, n_plist = 0;
  155.  
  156. unsigned int nreg = 0, ndoor = 0, ntrap = 0, nmons = 0, nobj = 0;
  157. unsigned int ndb = 0, nwalk = 0, npart = 0, ndig = 0, nlad = 0;
  158. #ifdef ALTARS
  159. unsigned int naltar = 0;
  160. #endif /* ALTARS /*/
  161.  
  162. unsigned int max_x_map, max_y_map;
  163.  
  164. extern int fatal_error;
  165. extern char* fname;
  166.  
  167. %}
  168.  
  169. %union
  170. {
  171.     int    i;
  172.     char*    map;
  173. }
  174.  
  175.  
  176. %token    <i> CHAR INTEGER
  177. %token    <i> MAZE_ID LEVEL_ID GEOMETRY_ID
  178. %token    <i> OBJECT_ID MONSTER_ID TRAP_ID DOOR_ID DRAWBRIDGE_ID MAZEWALK_ID
  179. %token    <i> REGION_ID RANDOM_OBJECTS_ID RANDOM_MONSTERS_ID RANDOM_PLACES_ID
  180. %token    <i> ALTAR_ID LADDER_ID NON_DIGGABLE_ID ROOM_ID
  181. %token    <i> DOOR_STATE LIGHT_STATE
  182. %token    <i> DIRECTION RANDOM_TYPE O_REGISTER M_REGISTER P_REGISTER A_REGISTER
  183. %token    <i> ALIGNMENT LEFT_OR_RIGHT CENTER TOP_OR_BOT ALTAR_TYPE UP_OR_DOWN
  184. %token    <i> ',' ':' '(' ')' '[' ']'
  185. %token    <map> STRING MAP_ID
  186. %type    <i> h_justif v_justif trap_name room_type door_state light_state
  187. %type    <i> alignment altar_type a_register
  188. %type    <map> string maze_def m_name o_name
  189. %start    file
  190.  
  191. %%
  192. file        : /* notthing */
  193.         | levels ;
  194.  
  195. levels        : level
  196.         | level levels ;
  197.  
  198. level        : maze_level ;
  199.  
  200. maze_level    : maze_def regions
  201.           {
  202.               int fout, i;
  203.  
  204.               if (fatal_error > 0)
  205.                   fprintf(stderr,"%s : %d errors detected. No output created!\n", fname, fatal_error);
  206.               else {
  207. #ifdef MACOS
  208.                   OSErr    result;
  209.                   
  210.                   result = Create(CtoPstr($1), 0, CREATOR, AUXIL_TYPE);
  211.                   (void)PtoCstr($1);
  212. #endif        
  213.                   fout = open($1, O_WRONLY | O_CREAT
  214. #if defined(MSDOS) || defined(MACOS)
  215.                           | O_BINARY
  216. #endif /* MSDOS || MACOS */
  217.                           , 0644);
  218.                   if (fout < 0) {
  219.                       yyerror("Can't open output file!!");
  220.                       exit(1);
  221.                   }
  222.                   maze.numpart = npart;
  223.                   maze.parts = (mazepart**) alloc(sizeof(mazepart*)*npart);
  224.                   for(i=0;i<npart;i++)
  225.                       maze.parts[i] = tmppart[i];
  226.                   write_maze(fout, &maze);
  227.                   (void) close(fout);
  228.                   npart = 0;
  229.               }
  230.           }
  231.  
  232. maze_def    : MAZE_ID ':' string
  233.           {
  234.               $$ = $3;
  235.           }
  236.  
  237. regions     : aregion
  238.         | aregion regions ;
  239.  
  240. aregion     : map_definition reg_init map_details
  241.           {
  242.             store_part();
  243.           }
  244.  
  245. map_definition    : map_geometry MAP_ID
  246.           {
  247.             tmppart[npart] = (mazepart *) alloc(sizeof(mazepart));
  248.             tmppart[npart]->halign = $<i>1 % 10;
  249.             tmppart[npart]->valign = $<i>1 / 10;
  250.             tmppart[npart]->nrobjects = 0;
  251.             tmppart[npart]->nloc = 0;
  252.             tmppart[npart]->nrmonst = 0;
  253.             scan_map($2);
  254.           }
  255.  
  256. map_geometry    : GEOMETRY_ID ':' h_justif ',' v_justif
  257.           {
  258.               $<i>$ = $<i>3 + ( $<i>5 * 10 );
  259.           }
  260.  
  261. h_justif    : LEFT_OR_RIGHT
  262.         | CENTER ;
  263.  
  264. v_justif    : TOP_OR_BOT
  265.         | CENTER ;
  266.  
  267. reg_init    : /* nothing */
  268.         | reg_init init_reg ;
  269.  
  270. init_reg    : RANDOM_OBJECTS_ID ':' object_list
  271.           {
  272.               if (tmppart[npart]->nrobjects)
  273.                   yyerror("Object registers already initialized!");
  274.               else {
  275.                   tmppart[npart]->robjects = (char *) alloc(n_olist);
  276.                   memcpy(tmppart[npart]->robjects, olist, n_olist);
  277.                   tmppart[npart]->nrobjects = n_olist;
  278.               }
  279.           }
  280.         | RANDOM_PLACES_ID ':' place_list
  281.           {
  282.               if (tmppart[npart]->nloc)
  283.                   yyerror("Location registers already initialized!");
  284.               else {
  285.                   register int i;
  286.                   tmppart[npart]->rloc_x = (char *) alloc(n_plist);
  287.                   tmppart[npart]->rloc_y = (char *) alloc(n_plist);
  288.                   for(i=0;i<n_plist;i++) {
  289.                       tmppart[npart]->rloc_x[i] = plist[i].x;
  290.                       tmppart[npart]->rloc_y[i] = plist[i].y;
  291.                   }
  292.                   tmppart[npart]->nloc = n_plist;
  293.               }
  294.           }
  295.         | RANDOM_MONSTERS_ID ':' monster_list
  296.           {
  297.               if (tmppart[npart]->nrmonst)
  298.                   yyerror("Monster registers already initialized!");
  299.               else {
  300.                   tmppart[npart]->rmonst = (char *) alloc(n_mlist);
  301.                   memcpy(tmppart[npart]->rmonst, mlist, n_mlist);
  302.                   tmppart[npart]->nrmonst = n_mlist;
  303.               }
  304.           }
  305.  
  306. object_list    : object
  307.           {
  308.               if (n_olist < MAX_REGISTERS)
  309.                   olist[n_olist++] = $<i>1;
  310.               else
  311.                   yyerror("Object list too long!");
  312.           }
  313.         | object ',' object_list
  314.           {
  315.               if (n_olist < MAX_REGISTERS)
  316.                   olist[n_olist++] = $<i>1;
  317.               else
  318.                   yyerror("Object list too long!");
  319.           }
  320.  
  321. monster_list    : monster
  322.           {
  323.               if (n_mlist < MAX_REGISTERS)
  324.                   mlist[n_mlist++] = $<i>1;
  325.               else
  326.                   yyerror("Monster list too long!");
  327.           }
  328.         | monster ',' monster_list
  329.           {
  330.               if (n_mlist < MAX_REGISTERS)
  331.                   mlist[n_mlist++] = $<i>1;
  332.               else
  333.                   yyerror("Monster list too long!");
  334.           }
  335.  
  336. place_list    : place
  337.           {
  338.               if (n_plist < MAX_REGISTERS)
  339.                   plist[n_plist++] = current_coord;
  340.               else
  341.                   yyerror("Location list too long!");
  342.           }
  343.         | place
  344.           {
  345.               if (n_plist < MAX_REGISTERS)
  346.                   plist[n_plist++] = current_coord;
  347.               else
  348.                   yyerror("Location list too long!");
  349.           } ',' place_list
  350.  
  351. map_details    : /* nothing */
  352.         | map_details map_detail ;
  353.  
  354. map_detail    : monster_detail
  355.         | object_detail
  356.         | door_detail
  357.         | trap_detail
  358.         | drawbridge_detail
  359.         | region_detail
  360.         | altar_detail
  361.         | mazewalk_detail
  362.         | ladder_detail
  363.         | diggable_detail ;
  364.  
  365. monster_detail    : MONSTER_ID ':' monster_c ',' m_name ',' coordinate
  366.           {
  367.               int token;
  368.  
  369.               tmpmonst[nmons] = (monster *) alloc(sizeof(monster));
  370.               tmpmonst[nmons]->x = current_coord.x;
  371.               tmpmonst[nmons]->y = current_coord.y;
  372.               tmpmonst[nmons]->class = $<i>3;
  373.               if (!$5)
  374.                   tmpmonst[nmons]->id = -1;
  375.               else {
  376.                   token = get_monster_id($5, (char) $<i>3);
  377.                   if (token == ERR) {
  378.                       yywarning("Illegal monster name!  Making random monster.");
  379.                       tmpmonst[nmons]->id = -1;
  380.                   } else
  381.                       tmpmonst[nmons]->id = token;
  382.               }
  383.               nmons++;
  384.           }
  385.  
  386. object_detail    : OBJECT_ID ':' object_c ',' o_name ',' coordinate
  387.           {
  388.               int token;
  389.  
  390.               tmpobj[nobj] = (object *) alloc(sizeof(object));
  391.               tmpobj[nobj]->x = current_coord.x;
  392.               tmpobj[nobj]->y = current_coord.y;
  393.               tmpobj[nobj]->class = $<i>3;
  394.               if (!$5)
  395.                   tmpobj[nobj]->id = -1;
  396.               else {
  397.                   token = get_object_id($5, (char) $<i>3);
  398.                   if (token == ERR) {
  399.                       yywarning("Illegal object name!  Making random object.");
  400.                       tmpobj[nobj]->id = -1;
  401.                   } else
  402.                       tmpobj[nobj]->id = token;
  403.               }
  404.               nobj++;
  405.           }
  406.  
  407. door_detail    : DOOR_ID ':' door_state ',' coordinate
  408.           {
  409.             tmpdoor[ndoor] = (door *) alloc(sizeof(door));
  410.             tmpdoor[ndoor]->x = current_coord.x;
  411.             tmpdoor[ndoor]->y = current_coord.y;
  412.             tmpdoor[ndoor]->mask = $<i>3;
  413.             ndoor++;
  414.           }
  415.  
  416. trap_detail    : TRAP_ID ':' trap_name ',' coordinate
  417.           {
  418.             tmptrap[ntrap] = (trap *) alloc(sizeof(trap));
  419.             tmptrap[ntrap]->x = current_coord.x;
  420.             tmptrap[ntrap]->y = current_coord.y;
  421.             tmptrap[ntrap]->type = $<i>3;
  422.             ntrap++;
  423.           }
  424.  
  425. drawbridge_detail: DRAWBRIDGE_ID ':' coordinate ',' DIRECTION ',' door_state
  426.            {
  427.             tmpdb[ndb] = (drawbridge *) alloc(sizeof(drawbridge));
  428.             tmpdb[ndb]->x = current_coord.x;
  429.             tmpdb[ndb]->y = current_coord.y;
  430.             tmpdb[ndb]->dir = db_dirs[$5];
  431.             if ( $<i>7 == D_ISOPEN )
  432.               tmpdb[ndb]->open = 1;
  433.             else if ( $<i>7 == D_CLOSED )
  434.               tmpdb[ndb]->open = 0;
  435.             else
  436.               yyerror("A drawbridge can only be open or closed!");
  437.             ndb++;
  438.            }
  439.  
  440. mazewalk_detail : MAZEWALK_ID ':' coordinate ',' DIRECTION
  441.           {
  442.             tmpwalk[nwalk] = (walk *) alloc(sizeof(walk));
  443.             tmpwalk[nwalk]->x = current_coord.x;
  444.             tmpwalk[nwalk]->y = current_coord.y;
  445.             tmpwalk[nwalk]->dir = $5;
  446.             nwalk++;
  447.           }
  448.  
  449. ladder_detail    : LADDER_ID ':' coordinate ',' UP_OR_DOWN
  450.           {
  451.             tmplad[nlad] = (lad *) alloc(sizeof(lad));
  452.             tmplad[nlad]->x = current_coord.x;
  453.             tmplad[nlad]->y = current_coord.y;
  454.             tmplad[nlad]->up = $<i>5;
  455.             nlad++;
  456.           }
  457.  
  458. diggable_detail : NON_DIGGABLE_ID ':' region
  459.           {
  460.             tmpdig[ndig] = (digpos *) alloc(sizeof(digpos));
  461.             tmpdig[ndig]->x1 = current_region.x1;
  462.             tmpdig[ndig]->y1 = current_region.y1;
  463.             tmpdig[ndig]->x2 = current_region.x2;
  464.             tmpdig[ndig]->y2 = current_region.y2;
  465.             ndig++;
  466.           }
  467.  
  468. region_detail    : REGION_ID ':' region ',' light_state ',' room_type
  469.           {
  470.             tmpreg[nreg] = (region *) alloc(sizeof(region));
  471.             tmpreg[nreg]->x1 = current_region.x1;
  472.             tmpreg[nreg]->y1 = current_region.y1;
  473.             tmpreg[nreg]->x2 = current_region.x2;
  474.             tmpreg[nreg]->y2 = current_region.y2;
  475.             tmpreg[nreg]->rlit = $<i>5;
  476.             tmpreg[nreg]->rtype = $<i>7;
  477.             nreg++;
  478.           }
  479.  
  480. altar_detail    : ALTAR_ID ':' coordinate ',' alignment ',' altar_type
  481.           {
  482. #ifndef ALTARS
  483.             yywarning("Altars are not allowed in this version!  Ignoring...");
  484. #else
  485.             tmpaltar[naltar] = (altar *) alloc(sizeof(altar));
  486.             tmpaltar[naltar]->x = current_coord.x;
  487.             tmpaltar[naltar]->y = current_coord.y;
  488.             tmpaltar[naltar]->align = $<i>5;
  489.             tmpaltar[naltar]->shrine = $<i>7;
  490.             naltar++;
  491. #endif /* ALTARS */
  492.           }
  493.  
  494. monster_c    : monster
  495.         | RANDOM_TYPE
  496.           {
  497.               $<i>$ = - MAX_REGISTERS - 1;
  498.           }
  499.         | m_register ;
  500.  
  501. object_c    : object
  502.         | RANDOM_TYPE
  503.           {
  504.               $<i>$ = - MAX_REGISTERS - 1;
  505.           }
  506.         | o_register;
  507.  
  508. m_name        : string
  509.         | RANDOM_TYPE
  510.           {
  511.               $$ = (char *) 0;
  512.           }
  513.  
  514. o_name        : string
  515.         | RANDOM_TYPE
  516.           {
  517.               $$ = (char *) 0;
  518.           }
  519.  
  520. trap_name    : string
  521.           {
  522.             int token = get_trap_type($1);
  523.             if (token == ERR)
  524.                 yyerror("unknown trap type!");
  525.             $<i>$ = token;
  526.           }
  527.         | RANDOM_TYPE
  528.  
  529. room_type    : string
  530.           {
  531.             int token = get_room_type($1);
  532.             if (token == ERR) {
  533.                 yywarning("Unknown room type!  Making ordinary room...");
  534.                 $<i>$ = OROOM;
  535.             } else
  536.                 $<i>$ = token;
  537.           }
  538.         | RANDOM_TYPE
  539.  
  540. coordinate    : coord
  541.         | p_register
  542.         | RANDOM_TYPE
  543.           {
  544.               current_coord.x = current_coord.y = -MAX_REGISTERS-1;
  545.           }
  546.  
  547. door_state    : DOOR_STATE
  548.         | RANDOM_TYPE
  549.  
  550. light_state    : LIGHT_STATE
  551.         | RANDOM_TYPE
  552.  
  553. alignment    : ALIGNMENT
  554.         | a_register
  555.         | RANDOM_TYPE
  556.           {
  557.               $<i>$ = - MAX_REGISTERS - 1;
  558.           }
  559.  
  560. altar_type    : ALTAR_TYPE
  561.         | RANDOM_TYPE
  562.  
  563. p_register    : P_REGISTER '[' INTEGER ']'
  564.           {
  565.             if ( $3 >= MAX_REGISTERS ) {
  566.                 yyerror("Register Index overflow!");
  567.             } else {
  568.                 current_coord.x = current_coord.y = - $3 - 1;
  569.             }
  570.           }
  571.  
  572. o_register    : O_REGISTER '[' INTEGER ']'
  573.           {
  574.             if ( $3 >= MAX_REGISTERS ) {
  575.                 yyerror("Register Index overflow!");
  576.             } else {
  577.                 $<i>$ = - $3 - 1;
  578.             }
  579.           }
  580.  
  581. m_register    : M_REGISTER '[' INTEGER ']'
  582.           {
  583.             if ( $3 >= MAX_REGISTERS ) {
  584.                 yyerror("Register Index overflow!");
  585.             } else {
  586.                 $<i>$ = - $3 - 1;
  587.             }
  588.           }
  589.  
  590. a_register    : A_REGISTER '[' INTEGER ']'
  591.           {
  592.             if ( $3 >= 3 ) {
  593.                 yyerror("Register Index overflow!");
  594.             } else {
  595.                 $<i>$ = - $3 - 1;
  596.             }
  597.           }
  598.  
  599. place        : coord
  600.  
  601. monster     : CHAR
  602.           {
  603.             if (check_monster_char((char) $1))
  604.                 $<i>$ = $1 ;
  605.             else {
  606.                 yyerror("unknown monster class!");
  607.                 $<i>$ = ERR;
  608.             }
  609.           }
  610.  
  611. object        : CHAR
  612.           {
  613.             char c;
  614.  
  615.             c = $1;
  616. #ifndef SPELLS
  617.             if ( c == '+') {
  618.                 c = '?';
  619.                 yywarning("Spellbooks are not allowed in this version! (converted into scroll)");
  620.             }
  621. #endif
  622.             if (check_object_char(c))
  623.                 $<i>$ = c;
  624.             else {
  625.                 yyerror("Unknown char class!");
  626.                 $<i>$ = ERR;
  627.             }
  628.           }
  629. string        : STRING
  630.  
  631. coord        : '(' INTEGER ',' INTEGER ')'
  632.           {
  633.             if ($2 < 0 || $2 > max_x_map ||
  634.                 $4 < 0 || $4 > max_y_map)
  635.                 yyerror("Coordinates out of map range!");
  636.             current_coord.x = $2;
  637.             current_coord.y = $4;
  638.           }
  639.  
  640. region        : '(' INTEGER ',' INTEGER ',' INTEGER ',' INTEGER ')'
  641.           {
  642.             if ($2 < 0 || $2 > max_x_map ||
  643.                 $4 < 0 || $4 > max_y_map ||
  644.                 $6 < 0 || $6 > max_x_map ||
  645.                 $8 < 0 || $8 > max_y_map)
  646.                 yyerror("Region out of map range!");
  647.             current_region.x1 = $2;
  648.             current_region.y1 = $4;
  649.             current_region.x2 = $6;
  650.             current_region.y2 = $8;
  651.           }
  652.  
  653.  
  654. %%
  655.  
  656. /* 
  657.  * Find the type of a room in the table, knowing its name.
  658.  */
  659.  
  660. int
  661. get_room_type(s)
  662. char *s;
  663. {
  664.     register int i;
  665.     
  666.     for(i=0; i < SHOPBASE -1; i++)
  667.         if (!strcmp(s, room_types[i].name))
  668.         return ((int) room_types[i].type);
  669.     return ERR;
  670. }
  671.  
  672. /* 
  673.  * Find the type of a trap in the table, knowing its name.
  674.  */
  675.  
  676. int
  677. get_trap_type(s)
  678. char *s;
  679. {
  680.     register int i;
  681.     
  682.     for(i=0; i < TRAPNUM - 1; i++)
  683.         if(!strcmp(s,trap_types[i].name))
  684.         return((int)trap_types[i].type);
  685.     return ERR;
  686. }
  687.  
  688. /* 
  689.  * Find the index of a monster in the table, knowing its name.
  690.  */
  691.  
  692. int
  693. get_monster_id(s, c)
  694. char *s;
  695. char c;
  696. {
  697.     register int i;
  698.     
  699.     for(i=0; mons[i].mname[0]; i++)
  700.         if(!strncmp(s, mons[i].mname, strlen(mons[i].mname))
  701.            && c == mons[i].mlet)
  702.         return i;
  703.     return ERR;
  704. }
  705.  
  706. /* 
  707.  * Find the index of an object in the table, knowing its name.
  708.  */
  709.  
  710. int
  711. get_object_id(s, c)
  712. char *s;
  713. char c;
  714. {
  715.     register int i;
  716.     
  717.     for(i=0; i<=NROFOBJECTS;i++)
  718.         if(objects[i].oc_name &&
  719.            !strncmp(s, objects[i].oc_name, strlen(objects[i].oc_name))
  720.            && c == objects[i].oc_olet)
  721.         return i;
  722.     return ERR;
  723. }
  724.  
  725. /* 
  726.  * Is the character 'c' a valid monster class ?
  727.  */
  728.  
  729. boolean
  730. check_monster_char(c)
  731. char c;
  732. {
  733.     register int i;
  734.     
  735.     for(i=0; mons[i].mname[0]; i++)
  736.         if( c ==  mons[i].mlet)
  737.         return 1;
  738.     return(0);
  739. }
  740.  
  741. /* 
  742.  * Is the character 'c' a valid object class ?
  743.  */
  744.  
  745. boolean
  746. check_object_char(c)
  747. char c;
  748. {
  749.     register int i;
  750.     
  751.     for(i=0; i<=NROFOBJECTS;i++)
  752.         if( c == objects[i].oc_olet)
  753.         return 1;
  754.     return 0;
  755. }
  756.  
  757. /* 
  758.  * Yep! LEX gives us the map in a raw mode.
  759.  * Just analyze it here.
  760.  */
  761.  
  762. void scan_map(map)
  763. char *map;
  764. {
  765.     register int i, len;
  766.     register char *s1, *s2;
  767.     int max_len = 0;
  768.     int max_hig = 0;
  769.     
  770.     /* First : find the max width of the map */
  771.  
  772.     s1 = map;
  773.     while (s1 && *s1) {
  774.         s2 = index(s1, '\n');
  775.         if (s2) {
  776.             if (s2-s1 > max_len)
  777.                 max_len = s2-s1;
  778.             s1 = s2 + 1;
  779.         } else {
  780.             if (strlen(s1) > max_len)
  781.                 max_len = strlen(s1);
  782.             s1 = (char *) 0;
  783.         }
  784.     }
  785.  
  786.     /* Then parse it now */
  787.  
  788.     while (map && *map) {
  789.         tmpmap[max_hig] = (char *) alloc(max_len);
  790.         s1 = index(map, '\n');
  791.         if (s1) {
  792.             len = s1 - map;
  793.             s1++;
  794.         } else {
  795.             len = strlen(map);
  796.             s1 = map + len;
  797.         }
  798.         for(i=0; i<len; i++)
  799.             switch(map[i]) {
  800.               case '-' : tmpmap[max_hig][i] = HWALL; break;
  801.               case '|' : tmpmap[max_hig][i] = VWALL; break;
  802.               case '+' : tmpmap[max_hig][i] = DOOR; break;
  803.               case 'S' : tmpmap[max_hig][i] = SDOOR; break;
  804.               case '{' : 
  805. #ifdef FOUNTAINS
  806.                   tmpmap[max_hig][i] = FOUNTAIN;
  807. #else
  808.                   tmpmap[max_hig][i] = ROOM;
  809.                   yywarning("Fountains are not allowed in this version!  Ignoring...");
  810. #endif
  811.                   break;
  812.               case '\\' : 
  813. #ifdef THRONES
  814.                   tmpmap[max_hig][i] = THRONE;
  815. #else
  816.                   tmpmap[max_hig][i] = ROOM;
  817.                   yywarning("Thrones are not allowed in this version!  Ignoring...");
  818. #endif
  819.                   break;
  820.               case 'K' : 
  821. #ifdef SINKS
  822.                   tmpmap[max_hig][i] = SINK;
  823. #else
  824.                   tmpmap[max_hig][i] = ROOM;
  825.                   yywarning("Sinks are not allowed in this version!  Ignoring...");
  826. #endif
  827.                   break;
  828.               case '}' : tmpmap[max_hig][i] = MOAT; break;
  829.               case '#' : tmpmap[max_hig][i] = CORR; break;
  830.               default  : tmpmap[max_hig][i] = ROOM; break;
  831.             }
  832.         while(i < max_len)
  833.             tmpmap[max_hig][i++] = ROOM;
  834.         map = s1;
  835.         max_hig++;
  836.     }
  837.  
  838.     /* Memorize boundaries */
  839.  
  840.     max_x_map = max_len - 1;
  841.     max_y_map = max_hig - 1;
  842.  
  843.     /* Store the map into the mazepart structure */
  844.  
  845.     tmppart[npart]->xsize = max_len;
  846.     tmppart[npart]->ysize = max_hig;
  847.     tmppart[npart]->map = (char **) alloc(max_hig*sizeof(char *));
  848.     for(i = 0; i< max_hig; i++)
  849.         tmppart[npart]->map[i] = tmpmap[i];
  850. }
  851.  
  852. /* 
  853.  * Here we want to store the maze part we just got.
  854.  */
  855.  
  856. void
  857. store_part()
  858. {
  859.     register int i;
  860.  
  861.     /* Ok, We got the whole part, now we store it. */
  862.     
  863.     /* The Regions */
  864.  
  865.     if(tmppart[npart]->nreg = nreg) {
  866.         tmppart[npart]->regions = (region**)alloc(sizeof(region*) * nreg);
  867.         for(i=0;i<nreg;i++)
  868.             tmppart[npart]->regions[i] = tmpreg[i];
  869.     }
  870.     nreg = 0;
  871.  
  872.     /* the doors */
  873.  
  874.     if(tmppart[npart]->ndoor = ndoor) {
  875.         tmppart[npart]->doors = (door **)alloc(sizeof(door *) * ndoor);
  876.         for(i=0;i<ndoor;i++)
  877.             tmppart[npart]->doors[i] = tmpdoor[i];
  878.     }
  879.     ndoor = 0;
  880.  
  881.     /* the traps */
  882.  
  883.     if(tmppart[npart]->ntraps = ntrap) {
  884.         tmppart[npart]->traps = (trap **)alloc(sizeof(trap*) * ntrap);
  885.         for(i=0;i<ntrap;i++)
  886.             tmppart[npart]->traps[i] = tmptrap[i];
  887.     }
  888.     ntrap = 0;
  889.  
  890.     /* the monsters */
  891.  
  892.     if(tmppart[npart]->nmonster = nmons) {
  893.         tmppart[npart]->monsters = (monster**)alloc(sizeof(monster*)*nmons);
  894.         for(i=0;i<nmons;i++)
  895.             tmppart[npart]->monsters[i] = tmpmonst[i];
  896.     }
  897.     nmons = 0;
  898.  
  899.     /* the objects */
  900.  
  901.     if(tmppart[npart]->nobjects = nobj) {
  902.         tmppart[npart]->objects = (object**)alloc(sizeof(object*)*nobj);
  903.         for(i=0;i<nobj;i++)
  904.             tmppart[npart]->objects[i] = tmpobj[i];
  905.     }
  906.     nobj = 0;
  907.  
  908.     /* the drawbridges */
  909.  
  910.     if(tmppart[npart]->ndrawbridge = ndb) {
  911.         tmppart[npart]->drawbridges = (drawbridge**)alloc(sizeof(drawbridge*)*ndb);
  912.         for(i=0;i<ndb;i++)
  913.             tmppart[npart]->drawbridges[i] = tmpdb[i];
  914.     }
  915.     ndb = 0;
  916.  
  917.     /* The walkmaze directives */
  918.  
  919.     if(tmppart[npart]->nwalk = nwalk) {
  920.         tmppart[npart]->walks = (walk**)alloc(sizeof(walk*)*nwalk);
  921.         for(i=0;i<nwalk;i++)
  922.             tmppart[npart]->walks[i] = tmpwalk[i];
  923.     }
  924.     nwalk = 0;
  925.  
  926.     /* The non_diggable directives */
  927.  
  928.     if(tmppart[npart]->ndig = ndig) {
  929.         tmppart[npart]->digs = (digpos **) alloc(sizeof(digpos*) * ndig);
  930.         for(i=0;i<ndig;i++)
  931.             tmppart[npart]->digs[i] = tmpdig[i];
  932.     }
  933.     ndig = 0;
  934.  
  935.     /* The ladders */
  936.  
  937.     if(tmppart[npart]->nlad = nlad) {
  938.         tmppart[npart]->lads = (lad **) alloc(sizeof(lad*) * nlad);
  939.         for(i=0;i<nlad;i++)
  940.             tmppart[npart]->lads[i] = tmplad[i];
  941.     }
  942.     nlad = 0;
  943. #ifdef ALTARS
  944.     /* The altars */
  945.  
  946.     if(tmppart[npart]->naltar = naltar) {
  947.         tmppart[npart]->altars = (altar**)alloc(sizeof(altar*) * naltar);
  948.         for(i=0;i<naltar;i++)
  949.             tmppart[npart]->altars[i] = tmpaltar[i];
  950.     }
  951.     naltar = 0;
  952. #endif /* ALTARS /**/
  953.     npart++;
  954.     n_plist = n_mlist = n_olist = 0;
  955. }
  956.  
  957. /* 
  958.  * Here we write the structure of the maze in the specified file (fd).
  959.  * Also, we have to free the memory allocated via alloc()
  960.  */
  961.  
  962. void
  963. write_maze(fd, maze)
  964. int fd;
  965. specialmaze *maze;
  966. {
  967.     char c;
  968.     short i,j;
  969.     mazepart *pt;
  970.  
  971.     c = 2;
  972.     (void) write(fd, &c, 1);    /* Header for special mazes */
  973.     (void) write(fd, &(maze->numpart), 1);    /* Number of parts */
  974.     for(i=0;i<maze->numpart;i++) {
  975.         pt = maze->parts[i];
  976.  
  977.         /* First, write the map */
  978.  
  979.         (void) write(fd, &(pt->halign), 1);
  980.         (void) write(fd, &(pt->valign), 1);
  981.         (void) write(fd, &(pt->xsize), 1);
  982.         (void) write(fd, &(pt->ysize), 1);
  983.         for(j=0;j<pt->ysize;j++) {
  984.             (void) write(fd, pt->map[j], pt->xsize);
  985.             free(pt->map[j]);
  986.         }
  987.         free(pt->map);
  988.  
  989.         /* The random registers */
  990.         (void) write(fd, &(pt->nrobjects), 1);
  991.         if(pt->nrobjects) {
  992.             (void) write(fd, pt->robjects, pt->nrobjects);
  993.             free(pt->robjects);
  994.         }
  995.         (void) write(fd, &(pt->nloc), 1);
  996.         if(pt->nloc) {
  997.         (void) write(fd,pt->rloc_x, pt->nloc);
  998.         (void) write(fd,pt->rloc_y, pt->nloc);
  999.         free(pt->rloc_x);
  1000.         free(pt->rloc_y);
  1001.         }
  1002.         (void) write(fd,&(pt->nrmonst), 1);
  1003.         if(pt->nrmonst) {
  1004.             (void) write(fd, pt->rmonst, pt->nrmonst);
  1005.             free(pt->rmonst);
  1006.         }
  1007.  
  1008.         /* subrooms */
  1009.         (void) write(fd, &(pt->nreg), 1);
  1010.         for(j=0;j<pt->nreg;j++) {
  1011.             (void) write(fd,(genericptr_t) pt->regions[j], sizeof(region));
  1012.             free(pt->regions[j]);
  1013.         }
  1014.         if(pt->nreg > 0)
  1015.         free(pt->regions);
  1016.  
  1017.         /* the doors */
  1018.         (void) write(fd,&(pt->ndoor),1);
  1019.         for(j=0;j<pt->ndoor;j++) {
  1020.             (void) write(fd,(genericptr_t) pt->doors[j], sizeof(door));
  1021.             free(pt->doors[j]);
  1022.         }
  1023.         if (pt->ndoor > 0)
  1024.         free(pt->doors);
  1025.  
  1026.         /* The traps */
  1027.         (void) write(fd,&(pt->ntraps), 1);
  1028.         for(j=0;j<pt->ntraps;j++) {
  1029.             (void) write(fd,(genericptr_t) pt->traps[j], sizeof(trap));
  1030.             free(pt->traps[j]);
  1031.         }
  1032.         if (pt->ntraps)
  1033.         free(pt->traps);
  1034.  
  1035.         /* The monsters */
  1036.         (void) write(fd, &(pt->nmonster), 1);
  1037.         for(j=0;j<pt->nmonster;j++) {
  1038.             (void) write(fd,(genericptr_t) pt->monsters[j], sizeof(monster));
  1039.             free(pt->monsters[j]);
  1040.         }
  1041.         if (pt->nmonster > 0)
  1042.         free(pt->monsters);
  1043.  
  1044.         /* The objects */
  1045.         (void) write(fd, &(pt->nobjects), 1);
  1046.         for(j=0;j<pt->nobjects;j++) {
  1047.             (void) write(fd,(genericptr_t) pt->objects[j], sizeof(object));
  1048.             free(pt->objects[j]);
  1049.         }
  1050.         if(pt->nobjects > 0)
  1051.         free(pt->objects);
  1052.  
  1053.         /* The drawbridges */
  1054.         (void) write(fd, &(pt->ndrawbridge),1);
  1055.         for(j=0;j<pt->ndrawbridge;j++) {
  1056.             (void) write(fd,(genericptr_t) pt->drawbridges[j], sizeof(drawbridge));
  1057.             free(pt->drawbridges[j]);
  1058.         }
  1059.         if(pt->ndrawbridge > 0)
  1060.         free(pt->drawbridges);
  1061.  
  1062.         /* The mazewalk directives */
  1063.         (void) write(fd, &(pt->nwalk), 1);
  1064.         for(j=0; j<pt->nwalk; j++) {
  1065.             (void) write(fd,(genericptr_t) pt->walks[j], sizeof(walk));
  1066.             free(pt->walks[j]);
  1067.         }
  1068.         if (pt->nwalk > 0)
  1069.         free(pt->walks);
  1070.  
  1071.         /* The non_diggable directives */
  1072.         (void) write(fd, &(pt->ndig), 1);
  1073.         for(j=0;j<pt->ndig;j++) {
  1074.             (void) write(fd,(genericptr_t) pt->digs[j], sizeof(digpos));
  1075.             free(pt->digs[j]);
  1076.         }
  1077.         if (pt->ndig > 0)
  1078.         free(pt->digs);
  1079.  
  1080.         /* The ladders */
  1081.         (void) write(fd, &(pt->nlad), 1);
  1082.         for(j=0;j<pt->nlad;j++) {
  1083.             (void) write(fd,(genericptr_t) pt->lads[j], sizeof(lad));
  1084.             free(pt->lads[j]);
  1085.         }
  1086.         if (pt->nlad > 0)
  1087.         free(pt->lads);
  1088. #ifdef ALTARS
  1089.         /* The altars */
  1090.         (void) write(fd, &(pt->naltar), 1);
  1091.         for(j=0;j<pt->naltar;j++) {
  1092.             (void) write(fd,(genericptr_t) pt->altars[j], sizeof(altar));
  1093.             free(pt->altars[j]);
  1094.         }
  1095.         if (pt->naltar > 0)
  1096.         free(pt->altars);
  1097. #endif /* ALTARS /**/
  1098.         free(pt);
  1099.     }
  1100. }
  1101.